﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.BusinessData.Infrastructure;
using Microsoft.BusinessData.Runtime;
using Microsoft.BusinessData.MetadataModel;
using Microsoft.BusinessData.MetadataModel.Collections;
using System.Collections;
using TFSCustomConnector;
using Microsoft.TeamFoundation.WorkItemTracking.Client;



namespace TFSCustomConnector
{
    public class TFSCustomConnector : ISystemUtility, IDisposable, IConnectionManager, IAdministrableSystem, ISystemPropertyValidator
    {
        #region IAdministrableSystem Members

        //definitions for administrative LobSystem properties
        public IList<AdministrableProperty> AdministrableLobSystemProperties
        {
            get
            {
                return new List<AdministrableProperty>()
                {
                    new AdministrableProperty("SystemUtilityTypeName","Name of the custom connector  utility",typeof(string),"SystemUtilityTypeName", typeof(string),true), 
                    new AdministrableProperty("SystemUtilityInstallDate","Date custom connector was installed",typeof(DateTime),"SystemUtilityInstallDate", typeof(DateTime),false)
                };
            }
        }

        //definitions for administrative LobSystemInstance properties
        public IList<AdministrableProperty> AdministrableLobSystemInstanceProperties
        {
            get
            {
                return new List<AdministrableProperty>()
                {
                   new AdministrableProperty("TFS Connection URL","connection path to TFS server",typeof(string),"TFSConnectionURL", typeof(string),true),
                   new AdministrableProperty("Default TFS WorkItem query filter","default filter for retreiving WorkItems",typeof(string),"DefaultWorkItemQuery", typeof(string),false)  
                };
            }
        }
        #endregion

        #region ISystemUtility Members

        public void ExecuteStatic(IMethodInstance methodInstance, ILobSystemInstance lobSystemInstance, object[] methodSignatureArgs, IExecutionContext context)
        {
            TFSConnectorHelper.Log("ExecuteStatic", methodInstance.MethodInstanceType.ToString(), "TFSWITCustomConnector", "Bug");
            
            if (methodInstance == null)
            {
                throw (new ArgumentNullException("methodInstance"));
            }
            if (lobSystemInstance == null)
            {
                throw (new ArgumentNullException("lobSystemInstance"));
            }
            if (methodSignatureArgs == null)
            {
                throw (new ArgumentNullException("args"));
            }

            //get entity level property through method instance
            //string DirectoryPath = (string)methodInstance.GetMethod().GetDataClass().GetProperties()[DirectoryPropertyName];

            //get method instance level property
            //string DirectoryPath = (string)methodInstance.GetProperties()[DirectoryPropertyName];

            //get lobsystem instance level property
            //string DirectoryPath = (string)lobSystemInstance.GetProperties()[DirectoryPropertyName];

            int ID;
            DynamicType template;
            string TfsConnURL = (string)lobSystemInstance.GetProperties()["TFSConnectionURL"];
            string TfsProjName = (string)methodInstance.GetMethod().GetDataClass().GetProperties()["TFSProjectName"];
            string TfsWIType = (string)methodInstance.GetMethod().GetDataClass().GetProperties()["TFSWorkItemType"]; //methodInstance.GetMethod().GetDataClass().Name
            string lobSystemName = lobSystemInstance.Name;

            TFSConnectorHelper.Log("ExecuteStatic", methodInstance.MethodInstanceType.ToString(), lobSystemName, TfsWIType);
            
            switch (methodInstance.MethodInstanceType)
            {
                case MethodInstanceType.SpecificFinder:                  
                    //methodSignatureArgs[0] - identifier
                    //methodSignatureArgs[1] - returned object

                    ID = (int)methodSignatureArgs[0];
                    template = GenerateDynamicItemStructure(methodInstance);
                    template = TFSConnectorHelper.FindWorkItem(TfsConnURL, ID, template, lobSystemName, TfsWIType);
                    methodSignatureArgs[1] = template;

                    break;

                case MethodInstanceType.Finder:                   
                    //methodSignatureArgs[0] - filter object
                    //methodSignatureArgs[1] - returned object list

                    string filter = (string)methodSignatureArgs[0];
                    template = GenerateDynamicItemStructure(methodInstance);
                    DynamicType[] dynItemsList = TFSConnectorHelper.QueryWorkItems(TfsConnURL, filter, template, lobSystemName, TfsWIType);
                    methodSignatureArgs[1] = dynItemsList;

                    break;

                case MethodInstanceType.Creator:
                    //methodSignatureArgs[0] - input creator object
                    //methodSignatureArgs[1] - returned id

                    template = methodSignatureArgs[0] as DynamicType;
                    int id = TFSConnectorHelper.CreateWorkItem(TfsConnURL, template, TfsWIType, TfsProjName, lobSystemName, TfsWIType);
                    methodSignatureArgs[1] = id;

                    break;

                case MethodInstanceType.Updater:
                    //methodSignatureArgs[0] - input id
                    //methodSignatureArgs[1] - input pre-updater object

                    ID = (int)methodSignatureArgs[0];
                    template = methodSignatureArgs[1] as DynamicType;
                    TFSConnectorHelper.UpdateWorkItem(TfsConnURL, ID, template, lobSystemName, TfsWIType);

                    break;

                case MethodInstanceType.Deleter:
                    //methodSignatureArgs[0] - input identifier

                    ID = (int)methodSignatureArgs[0];
                    TFSConnectorHelper.DestroyWorkItem(TfsConnURL, ID, lobSystemName, TfsWIType);

                    break;
            }
        }

        private DynamicType GenerateDynamicItemStructure(IMethodInstance methodInstance)
        {
            string IdentifierName = null;
            DynamicType dt = new DynamicType();

            ITypeDescriptor typeDescriptor = (methodInstance.MethodInstanceType == MethodInstanceType.Finder) ?
                methodInstance.GetMethod().GetParameters()[1].GetRootTypeDescriptor().GetChildTypeDescriptors()[0] :
                methodInstance.GetMethod().GetParameters()[1].GetRootTypeDescriptor();

            foreach (ITypeDescriptor childDescpritor in typeDescriptor.GetChildTypeDescriptors())
            {
                dt.Add(childDescpritor.Name, null);
                if (childDescpritor.IsIdentifierSet) IdentifierName = childDescpritor.GetIdentifier().Name;
            }

            if (IdentifierName == null) throw (new ArgumentNullException("Identifier is absent"));

            return dt;
        }

        public virtual IEnumerator CreateEntityInstanceDataEnumerator(Object rawAdapterEntityInstanceStream, ISharedEntityState sharedEntityState)
        {
            return ((IEnumerable)rawAdapterEntityInstanceStream).GetEnumerator();
        }
        #endregion
        #region ITypeReflector
        public ITypeReflector DefaultTypeReflector
        {
            get
            {
                return null;
            }
        }

        #endregion
        #region DefaultConnectionManager
        public IConnectionManager DefaultConnectionManager
        {
            get
            {
                return null;
            }
        }
        #endregion
        #region IConnectionManager Members

        public void CloseConnection(object connection)
        {

        }

        public void FlushConnections()
        {

        }

        public object GetConnection()
        {
            return null;
        }

        public void Initialize(ILobSystemInstance properties)
        {

        }

        #endregion
        #region IDisposable Members

        public void Dispose()
        {


        }
        #endregion
        #region ISystemPropertyValidator

        public void ValidateLobSystemInstanceProperty(string name, ref object value, string metadataObjectName, Type metadataObjectType)
        {
            if (name == "TFSConnectionURL")
            {
               // TFSConnectorHelper.ConnectToTFS(value as string);
            }
        }

        public void ValidateLobSystemProperty(string name, ref object value, string metadataObjectName, Type metadataObjectType)
        {
            //throw new NotImplementedException();
        }

#endregion
    }
}
